package com.zzyl.nursing.service.impl;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;

import com.aliyuncs.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zzyl.common.constant.HttpStatus;
import com.zzyl.common.core.page.TableDataInfo;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.DateUtils;
import com.zzyl.common.utils.UserThreadLocal;
import com.zzyl.nursing.dto.ReservationDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.mapper.ReservationMapper;
import com.zzyl.nursing.domain.Reservation;
import com.zzyl.nursing.service.IReservationService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

/**
 * 预约信息Service业务层处理
 *
 * @author alexis
 * @date 2025-06-02
 */
@Slf4j
@Service
public class ReservationServiceImpl extends ServiceImpl<ReservationMapper, Reservation> implements IReservationService {
    @Autowired
    private ReservationMapper reservationMapper;

    /**
     * 查询预约信息
     *
     * @param id 预约信息主键
     * @return 预约信息
     */
    @Override
    public Reservation selectReservationById(Long id) {
        return reservationMapper.selectById(id);
    }

    /**
     * 查询预约信息列表
     *
     * @param reservation 预约信息
     * @return 预约信息
     */
    @Override
    public List<Reservation> selectReservationList(Reservation reservation) {
        return reservationMapper.selectReservationList(reservation);
    }

    /**
     * 新增预约信息
     *
     * @param reservation 预约信息
     * @return 结果
     */
    @Override
    public int insertReservation(Reservation reservation) {
        return reservationMapper.insert(reservation);
    }

    /**
     * 修改预约信息
     *
     * @param reservation 预约信息
     * @return 结果
     */
    @Override
    public int updateReservation(Reservation reservation) {
        return reservationMapper.updateById(reservation);
    }

    /**
     * 批量删除预约信息
     *
     * @param ids 需要删除的预约信息主键
     * @return 结果
     */
    @Override
    public int deleteReservationByIds(Long[] ids) {
        return reservationMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除预约信息信息
     *
     * @param id 预约信息主键
     * @return 结果
     */
    @Override
    public int deleteReservationById(Long id) {
        return reservationMapper.deleteById(id);
    }

    /**
     * 查询当天取消预约数量
     *
     * @return
     */
    @Override
    public Long cancelledCount() {
        Long userId = UserThreadLocal.getUserId();
        long time = System.currentTimeMillis();
        LocalDateTime localDateTime = LocalDateTimeUtil.of(time);
        LocalDateTime startTime = localDateTime.toLocalDate().atStartOfDay();
        LocalDateTime endTime = startTime.plusDays(1);

        LambdaQueryWrapper<Reservation> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Reservation::getStatus, 2)
                .eq(Reservation::getCreateBy, userId)
                .between(Reservation::getCreateTime, startTime, endTime);

        return reservationMapper.selectCount(wrapper);
    }

    /**
     * 查询每个时间段剩余预约次数
     *
     * @return
     */
    @Override
    public List<Map<String, Object>> countByTime() {
        long time = System.currentTimeMillis();
        LocalDateTime localDateTime = LocalDateTimeUtil.of(time);
        LocalDateTime startTime = localDateTime.toLocalDate().atStartOfDay();
        LocalDateTime endTime = startTime.plusDays(1);

        return reservationMapper.countByTime(startTime, endTime);
    }

    /**
     * 新增预约
     *
     * @param reservationDto
     */
    @Override
    public void saveReservation(ReservationDto reservationDto) {
        // 验证时间段规则
        LocalDateTime time = reservationDto.getTime();
        int minute = time.getMinute();
        if (minute % 30 != 0) {
            throw new BaseException("预约时间必须为整点或30分钟间隔");
        }
        if (time.isBefore(LocalDateTimeUtil.now())){
            throw new BaseException("不能预约过去时间");
        }

        //姓名和手机号非空校验
        if (StringUtils.isEmpty(reservationDto.getName()) ||StringUtils.isEmpty(reservationDto.getMobile())){
            throw new BaseException("姓名或手机号不能为空");
        }

        //查询该时间段是否有6个预约
        LambdaQueryWrapper<Reservation> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Reservation::getTime, reservationDto.getTime())
                .ne(Reservation::getStatus,2);
        Long count = reservationMapper.selectCount(wrapper);
        if (count >=6){
            throw new BaseException("该时间段已约满");
        }

        //查询同一个手机、同一个时间段是否有预约
        wrapper.eq(Reservation::getMobile, reservationDto.getMobile());
        Reservation reservation = reservationMapper.selectOne(wrapper);

        if (ObjectUtil.isNotEmpty(reservation)) {
            throw new BaseException("该时间段已经有预约了");
        }

        reservation = BeanUtil.toBean(reservationDto, Reservation.class);
        reservation.setStatus(0);

        reservationMapper.insert(reservation);

    }

    /**
     * 分页查询预约
     *
     * @param pageNum
     * @param pageSize
     * @param status
     * @return
     */
    @Override
    public TableDataInfo pageReservation(Integer pageNum, Integer pageSize, Integer status) {
        Page page = Page.of(pageNum, pageSize);

        LambdaQueryWrapper<Reservation> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Reservation::getStatus, status);

        page = page(page, wrapper);

        TableDataInfo tableDataInfo = new TableDataInfo<>(page.getRecords(), page.getTotal());
        tableDataInfo.setCode(HttpStatus.SUCCESS);
        tableDataInfo.setMsg("操作成功");

        return tableDataInfo;
    }

    /**
     * 取消预约
     *
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void cancelReservation(Long id) {
        Reservation reservation = reservationMapper.selectById(id);
        if (reservation == null || reservation.getStatus() != 0) {
            throw new BaseException("当前状态不允许取消");
        }

        LambdaUpdateWrapper<Reservation> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(Reservation::getStatus, 2)
                .eq(Reservation::getStatus, 0)
                .eq(Reservation::getId, id);
        int update = reservationMapper.update(null, wrapper);
        if (update != 1) {
            throw new BaseException("预约不存在!");
        }
    }

    /**
     * 定时更新预约状态
     */
    @Override
    public void updateReservationStatus() {
        //若依前端设置定时任务，每个小时的01和31分执行更新
        LocalDateTime endTime = LocalDateTime.now();
        LocalDateTime startTime = endTime.minusMinutes(30);
        
        LambdaUpdateWrapper<Reservation> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(Reservation::getStatus,3)
                .eq(Reservation::getStatus,0)
                .between(Reservation::getTime,startTime,endTime);

        int count = reservationMapper.update(null,wrapper);
        log.info("已过期处理预约数量：{}", count);

    }


}
